/*
 * BlackLightning.PluginLib.Modules.RawBLPacket
 * Andy Tidball
 * 
 * Project: Black Lightning Plugin Library
 * Copyright: GNU General Public License
 */

using System;
using System.Text.RegularExpressions;

namespace BlackLightning.PluginLib.Modules {
    /// <summary>
    /// A packet which doesn't break the data string down into any more detail.
    /// </summary>
    [Serializable]
    public class RawBLPacket : BLPacket {
        // member data
        private string _Data; // the packet's data

        /// <summary>
        /// Creates a new RawBLPacket.
        /// </summary>
        /// <param name="Source">The program that the packet came from.</param>
        /// <param name="Destination">The program that the packet will be delivered to.</param>
        /// <param name="Data">The data string contained in the packet.</param>
        public RawBLPacket(Program Source, Program Destination, string Data)
            : base(Source, Destination, Data) {
            _Data = Data;
        }

        /// <summary>
        /// The data contained in the packet.
        /// </summary>
        public string Data {
            get {
                return _Data;
            }
            set {
                _Data = value;
            }
        }

        /// <summary>
        /// Retrieves the packet's data.
        /// </summary>
        /// <returns>The packet's data string.</returns>
        public override string CreateOutput() {
            return _Data;
        }

        /// <summary>
        /// Copy constructor.
        /// </summary>
        /// <param name="P">The RawBLPacket to create a copy of.</param>
        /// <param name="DeepCopyOrNextState">True to make a deep copy of the given packet, false to instead use the given packet as the new packet's previous state.</param>
        protected RawBLPacket(RawBLPacket P, bool DeepCopyOrNextState)
            : base(P, DeepCopyOrNextState) {
            _Data = P._Data;
        }

        /// <summary>
        /// Creates a deep copy of the packet.
        /// </summary>
        /// <returns>A deep copy of the packet.</returns>
        public override object Clone() {
            return new RawBLPacket(this, true);
        }

        /// <summary>
        /// Creates a new RawBLPacket that has this RawBLPacket as its PreviousState.
        /// </summary>
        /// <returns>A new RawBLPacket that has this one as its PreviousState.</returns>
        internal override BLPacket GetNextState() {
            return new RawBLPacket(this, false);
        }
    }

    /// <summary>
    /// A BLPacketFilter to use with RawBLPackets.
    /// </summary>
    [Serializable]
    public class RawBLPacketFilter : BLPacketFilter {
        // member data
        private string _DataString = null; // the string to match against the packet's data
        private Regex  _DataRegex  = null; // the regular expression to match against the packet's data

        /// <summary>
        /// Creates a new RawBLPacketFilter.
        /// </summary>
        public RawBLPacketFilter() {
        }

        /// <summary>
        /// Creates a new RawBLPacketFilter.
        /// </summary>
        /// <param name="Source">The source program to match against the packet's source.</param>
        /// <param name="Destination">The destination program to match against the packet's destination.</param>
        public RawBLPacketFilter(Program Source, Program Destination)
            : base(Source, Destination) {
        }

        /// <summary>
        /// Creates a new RawBLPacketFilter.
        /// </summary>
        /// <param name="Source">The source program to match against the packet's source.</param>
        /// <param name="Destination">The destination program to match against the packet's destination.</param>
        /// <param name="Input">The input string to match against the packet's raw input.</param>
        public RawBLPacketFilter(Program Source, Program Destination, string Input)
            : base(Source, Destination) {
            _DataString = Input;
        }

        /// <summary>
        /// Creates a new RawBLPacketFilter.
        /// </summary>
        /// <param name="Source">The source program to match against the packet's source.</param>
        /// <param name="Destination">The destination program to match against the packet's destination.</param>
        /// <param name="Input">The regular expression to match against the packet's raw input.</param>
        public RawBLPacketFilter(Program Source, Program Destination, Regex Input)
            : base(Source, Destination) {
            _DataRegex = Input;
        }

        /// <summary>
        /// The string to match against the packet's data string.
        /// </summary>
        public string DataString {
            get {
                return _DataString;
            }
            set {
                _DataString = value;
            }
        }

        /// <summary>
        /// The regular expression to match against the packet's data string.
        /// </summary>
        public Regex DataRegex {
            get {
                return _DataRegex;
            }
            set {
                _DataRegex = value;
            }
        }

        /// <summary>
        /// Matches the packet's dynamic data against the filter.
        /// </summary>
        /// <param name="Packet">The packet to match against the filter.</param>
        /// <returns>True if the packet's dynamic data matches the current setup of the filter, false if it does not.</returns>
        public override bool DynamicMatch(BLPacket Packet) {
            // make sure this is a RawBLPacket
            RawBLPacket P = Packet as RawBLPacket;
            if (P == null) {
                return false;
            }

            // match the data string
            if (this.DataString != null && P.Data != this.DataString) {
                return false;
            }

            // match the data regular expression
            // Regexes seem to use \n for newlines rather than Environment.NewLine
            // Since we're using the latter, do a replacement before matching
            if (this.DataRegex != null && !this.DataRegex.IsMatch(P.Data.Replace(Environment.NewLine, "\n"))) {
                return false;
            }

            // everything passed, match the base packet data
            return base.DynamicMatch(P);
        }
    }
}
